package com.xuanyuanxinyu.utils

import android.annotation.SuppressLint
import android.app.ActivityManager
import android.content.Context
import android.os.Build
import android.os.Environment
import android.os.StatFs
import android.text.TextUtils
import android.text.format.Formatter
import android.util.Log
import java.io.BufferedReader
import java.io.FileReader
import java.io.IOException
import java.lang.Float
import kotlin.math.ceil

/**
 * @author ken.luo
 * @version V1.0
 * @FileName: SystemUtils
 * @Description: 系统工具类方法
 * @date 2023/4/4
 * @email 424533553@qq.com
 */
object MemoryUtils {
    /**
     * RAM 手机总的RAM大小,单位GB
     * @return 手机RAM内存大小, 返回1GB/2GB/3GB/4GB/8G/16G
     */
    val totalRam : Int
        get() {
            val path = "/proc/meminfo"
            var ramMemorySize : String? = null
            var totalRam = 0
            try {
                val fileReader = FileReader(path)
                val br = BufferedReader(fileReader,4096)
                ramMemorySize = br.readLine().split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1]
                br.close()
            } catch (e : Exception) {
                e.printStackTrace()
            }
            if (ramMemorySize != null) {
                totalRam = ceil(Float.valueOf(ramMemorySize.toFloat() / (1024 * 1024)).toDouble()).toInt()
            }
            return totalRam
        }
    
    /**
     * @return 手机ROM内存大小，返回 64G/128G/256G/512G
     */
    val totalRom : String
        get() {
            val dataDir = Environment.getDataDirectory()
            val stat = StatFs(dataDir.path)
            val blockSize = stat.blockSizeLong
            val totalBlocks = stat.blockCountLong
            val size = totalBlocks * blockSize
            val GB = (1024 * 1024 * 1024).toLong()
            val deviceRomMemoryMap = longArrayOf(2 * GB,4 * GB,8 * GB,16 * GB,32 * GB,64 * GB,128 * GB,256 * GB,512 * GB,1024 * GB,2048 * GB)
            val displayRomSize = arrayOf("2GB","4GB","8GB","16GB","32GB","64GB","128GB","256GB","512GB","1024GB","2048GB")
            var i : Int
            i = 0
            while (i < deviceRomMemoryMap.size) {
                if (size <= deviceRomMemoryMap[i]) {
                    break
                }
                if (i == deviceRomMemoryMap.size) {
                    i--
                }
                i++
            }
            return displayRomSize[i]
        }
    
    /**
     * * 获取android总运行内存大小
     * * @param context
     * *
     */
    fun getTotalMemory(context : Context) : Long {
        // 系统内存信息文件
        val str1 = "/proc/meminfo"
        val str2 : String
        val arrayOfString : Array<String>
        var initialMemory : Long = 0
        try {
            val localFileReader = FileReader(str1)
            val localBufferedReader = BufferedReader(localFileReader,8192)
            // 读取meminfo第一行，系统总内存大小
            str2 = localBufferedReader.readLine()
            arrayOfString = str2.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
            for (num in arrayOfString) {
                Log.i(str2,num + "\t")
            }
            // 获得系统总内存，单位是KB
            val i = arrayOfString[1].toInt()
            //int值乘以1024转换为long类型
            initialMemory = i * 1024L
            localBufferedReader.close()
        } catch (e : IOException) {
            e.printStackTrace()
        }
        //获取MB
        return initialMemory / 1024 / 1024
    }
    
    /**
     * * 获取android当前可用运行内存大小
     * * @param context
     * *
     */
    fun getAvailMemory(context : Context) : String {
        val am = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        val mi = ActivityManager.MemoryInfo()
        am.getMemoryInfo(mi)
        // mi.availMem; 当前系统的可用内存  // 将获取的内存大小规格化
        return Formatter.formatFileSize(context,mi.availMem)
    }
    
    /**
     * * 获取android总运行内存大小
     * * @param context
     * *
     */
    fun getTotalMemoryString(context : Context?) : String {
        // 系统内存信息文件
        val str1 = "/proc/meminfo"
        val str2 : String
        val arrayOfString : Array<String>
        var initialMemory : Long = 0
        try {
            val localFileReader = FileReader(str1)
            val localBufferedReader = BufferedReader(localFileReader,8192)
            // 读取meminfo第一行，系统总内存大小
            str2 = localBufferedReader.readLine()
            arrayOfString = str2.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
            for (num in arrayOfString) {
                Log.i(str2,num + "\t")
            }
            // 获得系统总内存，单位是KB
            val i = arrayOfString[1].toInt()
            //int值乘以1024转换为long类型
            initialMemory = i * 1024L
            localBufferedReader.close()
        } catch (e : IOException) {
            e.printStackTrace()
        }
        // Byte转换为KB或者MB，内存大小规格化
        return Formatter.formatFileSize(context,initialMemory)
    }
    
    /**
     * 方法名：getMemoryInfo()
     * 功    能：获取手机总存储,可用存储
     * 参    数：无
     * 返回值：long
     */
    fun getMemoryInfo(context : Context) : Long {
        //获取到手机数据文件
        val path = Environment.getDataDirectory()
        //获取一个磁盘的状态对象
        val stat = StatFs(path.path)
        //获得一个扇区的大小
        val blockSizes = stat.blockSize.toLong()
        //获取扇区总数
        val totalBlocks = stat.blockCount.toLong()
        //获得可用扇区数量
        val availableBlocks = stat.availableBlocks.toLong()
        //获得总存储空间,MB
        //获得总存储空间
        val totalMemory = Formatter.formatFileSize(context,blockSizes * totalBlocks)
        //获得可用存储空间
        val availableMemory = Formatter.formatFileSize(context,availableBlocks * blockSizes);
        return blockSizes * totalBlocks / 1024 / 1024
    }
    
    /**
     * 如果小米手机获取Build.MODEL的结果是M2004J19C这样的格式
     * 那么使用反射获取小米手机型号 例如：Redmi note 9
     */
    val xiaoMiModel : String
        get() {
            var deviceName = ""
            try {
                @SuppressLint("PrivateApi") val c = Class.forName("android.os.SystemProperties")
                @SuppressLint("PrivateApi") val m = c.getDeclaredMethod("get",String::class.java)
                m.isAccessible = true
                deviceName = m.invoke(null,"ro.product.vendor.marketname") as String
                if (TextUtils.isEmpty(deviceName)) {
                    deviceName = m.invoke(null,"ro.product.marketname") as String
                }
                Log.d("WorkPhoneCheck","deviceName: $deviceName")
            } catch (e : Throwable) {
                e.printStackTrace()
            }
            return if (TextUtils.isEmpty(deviceName)) Build.MODEL else deviceName
        }
    
    /**
     *
     * @param context 上下文对象
     * @return  获取内存大小
     */
    fun getMemorySize(context : Context) : Int {
        val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        return activityManager.memoryClass
    }
    
    /*********************************************************/
    
    /**
     * 1.可使用的内存大小 /data
     */
    fun getMemoryAvaliSpace(context : Context) : String {
        //1.获取内存可用大小,内存路径
        val path = Environment.getDataDirectory().absolutePath
        val memoryAvaliSpace : String = Formatter.formatFileSize(context, getAvailSpace(path))
        Log.d("内存测试===","memoryAvaliSpace =$memoryAvaliSpace   ,path = $path")
        return memoryAvaliSpace
    }
    
    /**
     * 2.获取sd卡可用大小，sd卡路径
     */
    fun getSDAvaliSpace(context : Context) : String {
        val sdPath = Environment.getExternalStorageDirectory().absolutePath
        val sdAvaliSpace : String = Formatter.formatFileSize(context, getAvailSpace(sdPath))
        Log.d("内存测试===","sdAvaliSpace =$sdAvaliSpace   ,sdPath = $sdPath    , avaliSpace = " + getAvailSpace(sdPath))
        return sdAvaliSpace
    }
    
    /**
     * 获取可利用的size
     */
    private fun getAvailSpace(path : String) : Long {
        //获取可用内存大小
        val statfs = StatFs(path)
        //获取可用区块的个数
        val count = statfs.availableBlocks.toLong()
        //获取区块大小
        val size = statfs.blockSize.toLong()
        //可用空间总大小
        return count * size
    }
    
    
}